#!/usr/bin/env python
# _*_ coding:utf-8 _*_

import threading
import selectors
import socket
import logging

FORMAT = '%(asctime)s %(thread)s %(threadName)s %(message)s'
logging.basicConfig(level=logging.INFO,format=FORMAT,datefmt="%Y-%m-%d %H:%M:%S")

class ChatServer:
    def __init__(self,bind=('127.0.0.1',111)):
        self.server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        self.bind = bind
        self.selector = selectors.DefaultSelector()
        self.coniner = {}
        self.lock = threading.Lock()
        
    def start(self):
        self.server.bind(self.bind)
        self.server.listen()
        self.server.setblocking(False)
        self.selector.register(self.server,events=selectors.EVENT_READ,data=self.accept)
        while True:
            events = self.selector.select()
            for key,mask in events:
                key.data(key.fileobj)

    def accept(self,sock:socket.socket):
        newsock,addr = sock.accept()
        self.coniner[addr] = newsock
        logging.info('接受了一个新的连接>>>{}'.format(addr))
        newsock.setblocking(False)
        self.selector.register(newsock,events=selectors.EVENT_READ,data=self.recv)

    def recv(self,newsocket:socket.socket):
        data = newsocket.recv(1024)
        logging.info('From {} 接受了一个新的数据>>>{}'.format(newsocket.getpeername(),data))
        if data == b'':
            with self.lock:
                self.coniner.pop(newsocket.getpeername())
            open_msg = '{} disconnect'.format(newsocket.getpeername()).encode()

            self.selector.unregister(newsocket)
            newsocket.close()
            return
        msg = 'From {} : {}'.format(newsocket.getpeername(),data.decode())
        with self.lock:
            for i in self.coniner.values():
                i.send(msg.encode())

    def stop(self):
        self.server.close()
        for i in self.coniner.values():
            i.close()

t = ChatServer()
t.start()
